//
// Created by twetec on 25-10-21.
//

#include <gtest/gtest.h>
#include <httplib.h>
#include <boost/url.hpp>

#include <network_prober/probe_detect/handle_http_probe_detect.h>

namespace tests::probe_detect {
namespace
{
TEST(HandleHttpProbeDetectTest, testCppHttpLibServer)
{
    httplib::Server server;

    server.Get("/", [](const httplib::Request &req, httplib::Response resp) {
        std::cout << "收到GET请求" << std::endl;
        resp.set_content("Hello World", "text/plain");
    });

    server.Get("/about", [](const httplib::Request &req, httplib::Response resp) {
        std::cout << "收到GET请求" << std::endl;
        resp.set_content("About page", "text/plain");
    });

    server.Post("/api/users", [](const httplib::Request &req, httplib::Response resp) {
        std::string body = req.body;

        std::cout << body << std::endl;

        resp.set_content("POST request received", "application/json");
    });

    std::cout << "开始监听：8080" << std::endl;

    server.listen("fd00:7860:5bfc:44d0:1de9:be6a:9f90:7f83", 8080);
}

TEST(HandleHttpProbeDetectTest, testCppHttpLibClient)
{
    httplib::Client client("http://[fd00:7860:5bfc:44d0:1de9:be6a:9f90:7f83]:8080");

    client.set_interface("fd00:7860:5bfc:44d0:1de9:be6a:9f90:7f83");

    client.set_connection_timeout(0, 5 * 1000 * 1000); // 300 milliseconds

    std::chrono::steady_clock::time_point start_time = std::chrono::steady_clock::now();

    client.set_logger([&](const httplib::Request& req, const httplib::Response& res) {
      auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count();
      std::cout << "✓ " << req.method << " " << req.path
                << " -> " << res.status << " (" << res.body.size() << " bytes, "
                << duration << "ms)" << std::endl;
    });

    client.set_error_logger([](const httplib::Error& err, const httplib::Request* req) {
        std::cerr << "✗ ";
        if (req) {
            std::cerr << req->method << " " << req->path << " ";
        }

        std::cerr << "failed: " << httplib::to_string(err);

        // Add specific guidance based on error type
        switch (err) {
        case httplib::Error::Connection:
          std::cerr << " (verify server is running and reachable)";
          break;
        case httplib::Error::SSLConnection:
          std::cerr << " (check SSL certificate and TLS configuration)";
          break;
        case httplib::Error::ConnectionTimeout:
          std::cerr << " (increase timeout or check network latency)";
          break;
        case httplib::Error::Read:
          std::cerr << " (server may have closed connection prematurely)";
          break;
        default:
          break;
        }
        std::cerr << std::endl;
    });

    httplib::Result result = client.Get("/aboutjjj");
    if (result) {
        std::cout << "resutl: " << result << std::endl;
        std::cout << "状态吗：" << result->status << std::endl;
        std::cout << "响应体: " << result->body << std::endl;
    }
    // std::cout << result->status << " " << result->body << std::endl;

    httplib::Headers headers {
        {"Content-Type", "text/plain"}
    };

    std::string body = R"({"name": "John", "age": 30})";

    std::cout << "mmmmm" << std::endl;

    httplib::Result res = client.Post("/api/users", headers, body, "");

    std::cout << res.get_request_header_value("Content-Type") << std::endl;

    std::cout << res->status << " " << res->body << std::endl;
}

TEST(HandleHTTPProbeDetectIPv4, testDetect)
{
    // 创建探测指令对象
    auto probeDetectInstructionPtr = std::make_shared<network_prober::probe_detect::HandleHTTPProbeDetectIPv4>(
        "192.168.0.108",
        "http://192.168.0.108:8080/about",
        "2",
        true,
        "1",
        R"(Accept: application/json\nAccept-Language: zh-CN,zh;q=0.9\nAuthorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NjEyNjczOTYsIm5iZiI6MTc2MDY2MjU5NiwiaWF0IjoxNzYwNjYyNTk2LCJ1c2VyX2lkIjoxLCJ1c2VyX2dyb3VwX2lkIjoxLCJwcm9iZV9pZCI6IiJ9.nV0kDIT7nPHczQ9soXfbThWdDTsCANdXBBfRJiPAdfs\nConnection: keep-alive\nReferer: http://172.16.3.115/\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36)",
        "",
        false,
        "",
        "",
        "",
        ""
    );

    // 监听指令执行结果(延迟了对象生命周期)
    probeDetectInstructionPtr->setOnDetectedCallback([](network_prober::probe_detect::HTTPProbeDetectResultIPv4&& result) {
        std::cout << result << std::endl;
    });

    // 执行指令
    probeDetectInstructionPtr->detect();

    // hold住线程
    while (getchar() != '\n');
}

TEST(HandleHTTPProbeDetectIPv6, testDetect)
{
    // 创建探测指令对象
    auto probeDetectInstructionPtr = std::make_shared<network_prober::probe_detect::HandleHTTPProbeDetectIPv6>(
        "fd00:7860:5bfc:44d0:1de9:be6a:9f90:7f83",
        "http://[fd00:7860:5bfc:44d0:1de9:be6a:9f90:7f83]:8080/about",
        "2",
        true,
        "1", //  目标端口
        "",  // 地址类型 ipv4/ipv6
        "",
        false,
        "",
        "",
        "",
        ""
    );

    // 监听指令执行结果(延迟了对象生命周期)
    probeDetectInstructionPtr->setOnDetectedCallback([](network_prober::probe_detect::HTTPProbeDetectResultIPv6&& result) {
        std::cout << result << std::endl;
    });

    // 执行指令
    probeDetectInstructionPtr->detect();

    // hold住线程
    while (getchar() != '\n');
}

TEST(HandleHTTPProbeDetectIPv4, testStrSplit)
{
    std::string str{R"(Accept: application/json\nAccept-Language: zh-CN,zh;q=0.9\nAuthorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NjEyNjczOTYsIm5iZiI6MTc2MDY2MjU5NiwiaWF0IjoxNzYwNjYyNTk2LCJ1c2VyX2lkIjoxLCJ1c2VyX2dyb3VwX2lkIjoxLCJwcm9iZV9pZCI6IiJ9.nV0kDIT7nPHczQ9soXfbThWdDTsCANdXBBfRJiPAdfs\nConnection: keep-alive\nReferer: http://172.16.3.115/\nUser-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36)"};

    std::size_t start = 0;
    std::size_t end = str.find("\\n", start);

    std::vector<std::string> btokens;
    btokens.reserve(10);

    while (end != std::string::npos) {
        btokens.push_back(str.substr(start, end - start));
        start = end + 2;
        end = str.find("\\n", start);
    }

    // 保存最后一部分
    btokens.push_back(str.substr(start));

    std::map<std::string, std::string> h;

    for (auto it = btokens.begin(); it != btokens.end(); it++) {
        std::cout << "***" << *it << std::endl;

        start = 0;
        end = it->find(": ", start);

        std::string key;
        while (end != std::string::npos) {
            key = it->substr(start, end - start);
            start = end + 2;
            end = it->find(": ", start);
        }

        h[key] = it->substr(start);
    }

    for (auto it = h.begin(); it != h.end(); it++) {
        std::cout << "%%%" << it->first << " >>> " << it->second << std::endl;
    }

    // while (ed != std::string::npos) {
    //     std::cout << "after: " << s.substr(st, ed - st) << std::endl;
    //     st = ed + 2;
    //     ed = s.find(": ", st);
    // }
}

TEST(HandleHTTPProbeDetectIPv4, testUrlParser)
{
    boost::urls::url url{"http://172.16.3.115:80/v1/obs/page?pageNum=1\u0026pageSize=100"};

    std::cout << "Scheme: " << url.scheme() << std::endl; // Output scheme (e.g., https)
    std::cout << "Host: " << url.host() << std::endl; // Output host (e.g., www.example.com)
    std::cout << "Port: " << url.port() << std::endl;
    std::cout << "Path: " << url.encoded_path() << std::endl; // Output path (e.g., /path/to/resource)
    std::cout << "Query: " << url.encoded_query() << std::endl;

    std::cout << url.host_ipv4_address() << std::endl;

    std::cout << url.path() << std::endl;
    std::cout << url.query() << std::endl;
}

}}